// $Id: char_traits.cpp 2 2009-09-02 08:47:42Z joseph2002 $
/*
 * Copyright 2008-2009 Joseph Wu
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
 *
 * For more information, see http://xpcomplus.sourceforge.net
 */

#define XPCOM_SOURCE

#include <xpcom/config.hpp>
#include <xpcom/char_traits.hpp>

namespace xpcom {

#ifdef XPCOM_USE_STD_CHAR_TRAITS
// Using standard char_traits, nothing here

#else // XPCOM_USE_STD_CHAR_TRAITS

#ifndef XPCOM_HAS_2BYTE_WCHAR_T

template <typename CharT>
int char_traits<CharT>::compare(
        const char_type* s1, const char_type* s2, std::size_t n)
{
    for ( ; n > 0; --n, ++s1, ++s2)
        if (!eq(*s1, *s2))
            return lt(*s1, *s2) ? -1 : +1;
    return 0;
}

template <typename CharT>
std::size_t char_traits<CharT>::length(const char_type* p)
{
    std::size_t n = 0;
    for ( ; !eq(*p, char_type()); ++p)
        ++n;
    return n;
}

template <typename CharT>
typename char_traits<CharT>::char_type*
char_traits<CharT>::copy(char_type* s1, const char_type* s2, std::size_t n)
{
    char_type* p = s1;
    for ( ; n > 0; --n, ++p, ++s2)
        assign(*p, *s2);
    return s1;
}

template <typename CharT>
typename char_traits<CharT>::char_type*
char_traits<CharT>::move(char_type* s1, const char_type* s2, std::size_t n)
{
    char_type* p = s1;
    if (s2 < p && p < s2 + n)
        for (p += n, s2 += n; n > 0; --n)
            assign(*--p, *--s2);
    else
        for ( ; n > 0; --n, ++p, ++s2)
            assign(*p, *s2);
    return s1;
}

template <typename CharT>
typename char_traits<CharT>::char_type*
char_traits<CharT>::assign(char_type* s, std::size_t n, char_type a)
{
    char_type* p = s;
    for ( ; n > 0; --n, ++p)
        assign(*p, a);
    return s;
}

template <typename CharT>
const typename char_traits<CharT>::char_type*
char_traits<CharT>::find(const char_type* s, std::size_t n, const char_type& a)
{
    for ( ; n > 0; --n, ++s)
        if (eq(*s, a))
            return s;
    return 0;
}

// Explicit instantiations
template class XPCOM_DECL char_traits<wchar>;

#endif // XPCOM_HAS_2BYTE_WCHAR_T

#endif // XPCOM_USE_STD_CHAR_TRAITS

} // namespace xpcom
